# -*- coding:utf-8 -*-

"""
单例模式，类的对象只能存在一个
"""

"""
实现__new__方法
将类的一个实例绑定到类变量_instance上
如果_instance为None，说明未实例化过，new一个该类的对象并返回
如果_instance不为None，直接返回_instance
"""
class Singleton1(object):
    def __new__(self, *args, **kwargs):
        if not hasattr(self, '_instance'):
            orig = super(Singleton1, self)
            self._instance = orig.__new__(self, *args, **kwargs)
        return self._instance

class MyClass1(Singleton1):
    a = 1

one = MyClass1()
two = MyClass1()

print(id(one))
print(id(two))
print(one == two)
print(one is two)

two.a = 3
print(one.a)
print("===========================================")

"""
共享属性，所有引用（实例、对象）拥有相同的属性和方法
__dict__属性指向同一个字典(dict)
"""
class Singleton2(object):
    _state = {}
    def __new__(self, *args, **kwargs):
        ob = super(Singleton2, self).__new__(self, *args, **kwargs)
        ob.__dict__ = self._state
        return ob

class MyClass2(Singleton2):
    a = 1

one = MyClass2()
two = MyClass2()

two.a = 3

# one 和 two 是两个不同的对象，id，==，is对比结果可以看出
print(id(one))
print(id(two))
print(one == two)
print(one is two)

# 但是one和two具有相同的（同一个）__dict__属性
print(id(one.__dict__))
print(id(two.__dict__))
print("===========================================")

"""
装饰器版本decorator
更好的做法
"""
def Singleton3(self, *args, **kwargs):
    instance = {}
    def getinstance():
        if self not in instance:
            instance[self] = self(*args, **kwargs)
        return instance[self]
    return getinstance

@Singleton3
class MyClass3(object):
    a = 1
    def __init__(self, x = 0):
        self.x = x

one = MyClass3()
two = MyClass3()
two.a = 3
print(one.a)
print(id(one))
print(id(two))
print(one == two)
print(one is two)
one.a = 1
print(one.x)
print(one.x)
print("===========================================")